import { _decorator, Component, Node, Vec3, instantiate, sp, Prefab } from "cc"
import ResManager from "../framework/ResManager"
import { Tween } from "cc"

const { ccclass, property } = _decorator

@ccclass("EffectManager")
export class EffectManager extends Component {
  static instance: EffectManager
  protected onLoad(): void {
    EffectManager.instance = this
  }
  protected onEnable(): void {}
  protected onDisable(): void {
    this.unscheduleAllCallbacks()
  }

  /**角色出场特效 */
  public playEffectRoleOut(pos: Vec3, outTime: number = 1) {
    const path = "prefabs/game/effect/effect_role_out"
    this.getEffectNodeWithPath(path).then((node) => {
      node.setPosition(pos.x,pos.y + 30)
      new Tween(node)
        .delay(outTime)
        .call(() => {
          node.destroy()
        })
        .start()
    })
  }

  /**敌人死亡特效 */
  public playActionMonsterDie(pos: Vec3) {
    ResManager.instance.loadRes("prefabs/game/effect/effect_bone", Prefab, (err, prefab: Prefab) => {
      if (prefab) {
        const nodeEffectBone = instantiate(prefab)
        this.node.addChild(nodeEffectBone)
        const nodeBone = nodeEffectBone.getChildByName("nodeBone")
        if (nodeBone) {
          for (let i: number = 0; i < 2; i++) {
            const newNode = instantiate(nodeBone)
            nodeEffectBone.addChild(newNode)
            nodeEffectBone.setPosition(pos)
          }
        }
        this.scheduleOnce(() => {
          const time: number = 0.7
          const randomMaxX: number = 500
          const randomMaxY: number = 500
          const randomAngle: number = 540
          const nodeHeadBone = nodeEffectBone.getChildByName("nodeHeadBone")
          if (nodeHeadBone) {
            nodeHeadBone.setSiblingIndex(nodeEffectBone.children.length - 1)
            const randomX: number = Math.random() * randomMaxX - randomMaxX * 0.5
            const randomY: number = 50 + Math.random() * randomMaxY
            const randomRotation: number = Math.random() * randomAngle * 0.5
            new Tween(nodeHeadBone).by(time, { positionY: -randomY }, { easing: "cubicIn" }).start()
            new Tween(nodeHeadBone).by(time, { positionX: randomX }).start()
            new Tween(nodeHeadBone)
              .delay(0.7 * time)
              .to(0.3 * time, { alpha: 0 })
              .start()
            new Tween(nodeHeadBone).by(time, { angle: randomRotation }).start()
          }
          for (let i: number = 0; i < nodeEffectBone.children.length; i++) {
            const node = nodeEffectBone.children[i]
            if (node.name !== "nodeHeadBone") {
              const randomX: number = Math.random() * randomMaxX - randomMaxX * 0.5
              const randomY: number = 140 + Math.random() * 20
              const randomRotation: number = Math.random() * randomAngle
              new Tween(node).by(time, { positionY: -randomY }, { easing: "cubicIn" }).start()
              new Tween(node).by(time, { positionX: randomX }).start()
              new Tween(node)
                .delay(0.7 * time)
                .to(0.3 * time, { alpha: 0 })
                .start()
              new Tween(node).by(time, { angle: randomRotation }).start()
            }
          }
          new Tween(nodeEffectBone)
            .delay(time)
            .call(() => {
              nodeEffectBone.destroy()
            })
            .start()
        })
      }
    })
  }

  private getEffectNodeWithPath(path: string): Promise<Node> {
    return new Promise((resolve, reject) => {
      ResManager.instance.loadRes(path, Prefab, (err, prefab: Prefab) => {
        if (err) {
          reject(err)
          return
        }
        if (prefab) {
          const node = instantiate(prefab)
          this.node.addChild(node)
          resolve(node)
        } else {
          reject(new Error("Prefab not found."))
        }
      })
    })
  }
}
